package com.example.admin.mybledemo.ota;

import java.util.ArrayList;
import java.util.List;

import cn.com.heaton.blelibrary.ble.BleLog;

public class OtaProtocol {

    // 服务UUID - V1版本
    public static final String APP_OTA_SERVICE_UID = "5265616C-6D70-6761-2D49-6E73696465AA";
    public static final String APP_OTA_WRITE_UID = "5265616C-6D71-6761-2D49-6E73696465AA";
    public static final String APP_OTA_VERSION_UID = "5265616C-6D72-6761-2D49-6E73696465AA";
    public static final String APP_OTA_NOTIFY = "5265616C-6D73-6761-2D49-6E73696465AA";
    
    // 服务UUID - V2版本
    public static final String APP_OTA_SERVICE_UID_V2 = "5265616C-6D80-6761-2D49-6E73696465AA";
    public static final String APP_OTA_WRITE_UID_V2 = "5265616C-6D81-6761-2D49-6E73696465AA";
    public static final String APP_OTA_VERSION_UID_V2 = "5265616C-6D82-6761-2D49-6E73696465AA";
    public static final String APP_OTA_NOTIFY_V2 = "5265616C-6D83-6761-2D49-6E73696465AA";
    
    // Boot模式服务UUID
    public static final String BOOT_OTA_SERVICE_UID = "5265616C-6D65-6761-2D49-6E73696465AA";
    public static final String BOOT_OTA_CMD_UID = "5265616C-6D66-6761-2D49-6E73696465AA";
    public static final String BOOT_OTA_ASK_UID = "5265616C-6D67-6761-2D49-6E73696465AA";

    // 协议命令
    private static final byte[] UPDATE_CMD = {0x63, 0x69, 0x6d, 0x72};
    private static final byte[] VERSION_REQ_CMD = {0x01, 0x00};
    private static final byte[] OTA_START_CMD = {0x01, 0x01};
    private static final byte[] OTA_BLOCK_CMD = {0x01, 0x04};
    private static final byte[] OTA_END_CMD = {0x01, 0x03};

    public static byte[] getUpdateCommand() {
        return UPDATE_CMD.clone();
    }

    public static byte[] getVersionRequestCommand() {
        return VERSION_REQ_CMD.clone();
    }

    public static byte[] getOtaStartCommand() {
        return OTA_START_CMD.clone();
    }

    public static byte[] getOtaEndCommand() {
        return OTA_END_CMD.clone();
    }

    /**
     * 构建第二阶段OTA开始命令（Flutter格式）
     * 格式: [01,01,...creditCode]
     * 
     * @param creditCode 凭证码（4字节，小端序）
     * @return OTA开始命令数据包
     */
    public static byte[] buildOtaStartCommand(String creditCode) {
        // 将凭证码转换为字节数组（4字节）
        byte[] creditBytes = hexStringToBytes(creditCode);
        if (creditBytes.length != 4) {
            // 如果不是4字节，填充或截断
            byte[] paddedBytes = new byte[4];
            System.arraycopy(creditBytes, 0, paddedBytes, 0, Math.min(creditBytes.length, 4));
            creditBytes = paddedBytes;
        }
        
        // 小端序转换
        byte[] creditBytesLE = reverseByteArray(creditBytes);
        
        // 构建命令：[0x01, 0x01] + creditCode(4字节,小端序)
        byte[] command = new byte[OTA_START_CMD.length + creditBytesLE.length];
        System.arraycopy(OTA_START_CMD, 0, command, 0, OTA_START_CMD.length);
        System.arraycopy(creditBytesLE, 0, command, OTA_START_CMD.length, creditBytesLE.length);
        
        return command;
    }

    /**
     * 构建块命令（Flutter格式）
     * 格式: [01,04, targetAddr(4字节,小端), targetSize(2字节,小端), blockFcs(3字节,小端)]
     * 
     * @param targetAddress 目标地址
     * @param blockSize 块大小
     * @param blockData 块数据（用于计算FCS）
     * @return 块命令数据包
     */
    public static byte[] buildBlockCommand(int targetAddress, int blockSize, byte[] blockData) {
        // 计算FCS校验（3字节）
        byte[] fcs = FcsUtil.calculateFCS(blockData);
        
        // 构建命令：[0x01, 0x04] + 地址(4字节,小端) + 大小(2字节,小端) + FCS(3字节)
        byte[] command = new byte[2 + 4 + 2 + 3]; // 总共11字节
        
        // 命令头
        command[0] = OTA_BLOCK_CMD[0]; // 0x01
        command[1] = OTA_BLOCK_CMD[1]; // 0x04
        
        // 目标地址（4字节，小端序）
        command[2] = (byte) (targetAddress & 0xFF);
        command[3] = (byte) ((targetAddress >> 8) & 0xFF);
        command[4] = (byte) ((targetAddress >> 16) & 0xFF);
        command[5] = (byte) ((targetAddress >> 24) & 0xFF);
        
        // 块大小（2字节，小端序）
        command[6] = (byte) (blockSize & 0xFF);
        command[7] = (byte) ((blockSize >> 8) & 0xFF);
        
        // FCS校验（3字节）
        System.arraycopy(fcs, 0, command, 8, 3);
        
        return command;
    }

    /**
     * 将块数据分割为32字节的数据包（Flutter格式）
     * 
     * @param blockData 完整的块数据
     * @return 32字节数据包列表
     */
    public static List<byte[]> splitBlockDataToPackets(byte[] blockData) {
        List<byte[]> packets = new ArrayList<>();
        final int DATA_SIZE = 32; // 与Flutter端保持一致
        
        for (int i = 0; i < blockData.length; i += DATA_SIZE) {
            int packetSize = Math.min(DATA_SIZE, blockData.length - i);
            byte[] packet = new byte[packetSize];
            System.arraycopy(blockData, i, packet, 0, packetSize);
            packets.add(packet);
        }
        
        return packets;
    }

    /**
     * 构建第二阶段OTA结束命令（Flutter格式）
     * 格式: [01, 03]
     * 
     * @return OTA结束命令数据包
     */
    public static byte[] buildOtaEndCommand() {
        return OTA_END_CMD.clone();
    }

    // 废弃的方法 - 替换为Flutter兼容的方法
    @Deprecated
    public static byte[] buildDataPacket(OtaBlock block) {
        // 这个方法格式不正确，应该使用新的方法
        throw new UnsupportedOperationException("请使用 buildBlockCommand 和 splitBlockDataToPackets 方法");
    }

    @Deprecated
    public static byte[] buildVerifyPacket(int checksum) {
        // 这个方法格式不正确，应该使用 buildOtaEndCommand
        throw new UnsupportedOperationException("请使用 buildOtaEndCommand 方法");
    }

    public static byte[] buildCredentialData(String macAddress, String creditCode) {
        // 获取当前存储的随机MAC地址
        RandomMacManager randomMacManager = RandomMacManager.getInstance();
        
        // 将凭证码转换为字节数组（4字节，小端序）
        byte[] creditBytes;
        if (creditCode.matches("[0-9A-Fa-f]+")) {
            // 如果是十六进制字符串，转换为字节
            creditBytes = hexStringToBytes(creditCode);
        } else {
            // 如果是ASCII字符串，直接转换
            creditBytes = creditCode.getBytes();
        }
        
        // 确保凭证码是4字节
        if (creditBytes.length != 4) {
            byte[] paddedBytes = new byte[4];
            System.arraycopy(creditBytes, 0, paddedBytes, 0, Math.min(creditBytes.length, 4));
            creditBytes = paddedBytes;
        }
        
        // 获取随机MAC字节（6字节）
        byte[] randomMacBytes = randomMacManager.getRandomMacBytes();
        
        // MAC Code（使用用户输入的MAC码）
        byte[] macCodeBytes = hexStringToBytes(macAddress);
        
        // 确保MAC码是8字节
        if (macCodeBytes.length != 8) {
            byte[] paddedMacCode = new byte[8];
            System.arraycopy(macCodeBytes, 0, paddedMacCode, 0, Math.min(macCodeBytes.length, 8));
            macCodeBytes = paddedMacCode;
        }
        
        // 转换为小端序（Flutter要求）
        byte[] creditBytesLE = reverseByteArray(creditBytes);
        byte[] randomMacBytesLE = reverseByteArray(randomMacBytes);
        // MAC码不进行小端序转换，与Flutter端保持一致
        byte[] macCodeBytesLE = macCodeBytes;
        
        // 构建凭证数据：[creditCode(4字节,小端)] + [randMac(6字节,小端)] + [macCode(8字节)]
        byte[] credentialData = new byte[4 + 6 + 8]; // 总共18字节
        
        int offset = 0;
        // 凭证码数据（4字节，小端序）
        System.arraycopy(creditBytesLE, 0, credentialData, offset, 4);
        offset += 4;
        
        // 随机MAC地址数据（6字节，小端序）
        System.arraycopy(randomMacBytesLE, 0, credentialData, offset, 6);
        offset += 6;
        
        // MAC Code数据（8字节，不进行小端序转换）
        System.arraycopy(macCodeBytesLE, 0, credentialData, offset, 8);
        
        // 添加调试日志
        BleLog.d("OtaProtocol", "构建凭证数据:");
        BleLog.d("OtaProtocol", "  creditCode原始: " + creditCode);
        BleLog.d("OtaProtocol", "  creditCode字节: " + bytesToHexString(creditBytes));
        BleLog.d("OtaProtocol", "  creditCode小端: " + bytesToHexString(creditBytesLE));
        BleLog.d("OtaProtocol", "  randomMac字节: " + bytesToHexString(randomMacBytes));
        BleLog.d("OtaProtocol", "  randomMac小端: " + bytesToHexString(randomMacBytesLE));
        BleLog.d("OtaProtocol", "  macCode原始: " + macAddress);
        BleLog.d("OtaProtocol", "  macCode字节: " + bytesToHexString(macCodeBytes));
        BleLog.d("OtaProtocol", "  macCode小端: " + bytesToHexString(macCodeBytesLE));
        BleLog.d("OtaProtocol", "  最终凭证数据: " + bytesToHexString(credentialData));
        BleLog.d("OtaProtocol", "  凭证数据长度: " + credentialData.length + " bytes");
        BleLog.d("OtaProtocol", "  凭证数据验证: " + (credentialData.length == 18 ? "OK" : "ERROR"));
        
        return credentialData;
    }
    
    /**
     * 十六进制字符串转字节数组
     */
    private static byte[] hexStringToBytes(String hexString) {
        hexString = hexString.replaceAll("\\s", "");
        if (hexString.length() % 2 != 0) {
            return new byte[0];
        }
        
        byte[] bytes = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            try {
                bytes[i / 2] = (byte) Integer.parseInt(hexString.substring(i, i + 2), 16);
            } catch (NumberFormatException e) {
                return new byte[0];
            }
        }
        return bytes;
    }
    
    /**
     * 字节数组反转（小端序转换）
     */
    private static byte[] reverseByteArray(byte[] bytes) {
        byte[] reversed = new byte[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            reversed[i] = bytes[bytes.length - 1 - i];
        }
        return reversed;
    }
    
    /**
     * 字节数组转十六进制字符串
     */
    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b & 0xFF));
        }
        return sb.toString().trim();
    }
}